package com.gss.entity.generator;

import com.gss.entity.sys.dto.*;
import io.swagger.annotations.ApiModelProperty;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * 实体类转换为标准sql
 */
public class ClassEntityToSql {

    public static void main(String[] args) {
        Class<SysUserDept> aClass = SysUserDept.class;

        List<ClassData> dataList = parseEntityClazz(aClass);
        List<ClassData> superList = parseEntityClazz(aClass.getSuperclass());
        dataList.addAll(superList);

        convertToSQL("sys_user_dept_role",dataList);
    }


    /**
     * 转换为标准sql
     * @param dataList
     */
    private static void convertToSQL(String tabName,List<ClassData> dataList) {
        StringBuilder builder = new StringBuilder();
        builder.append("DROP TABLE IF EXISTS \"public\".\""+ tabName +"\";\n");
        builder.append("DROP SEQUENCE IF EXISTS \"public\".\""+ tabName +"_id_seq\";\n");
        builder.append("CREATE SEQUENCE \"public\".\""+ tabName +"_id_seq\" \n");
        builder.append("INCREMENT 1\n");
        builder.append("MINVALUE  1\n");
        builder.append("MAXVALUE 9223372036854775807\n");
        builder.append("START 1\n");
        builder.append("CACHE 1;\n");
        builder.append("\n");

        builder.append("CREATE TABLE IF NOT EXISTS \"public\".\""+ tabName +"\"(\n");
        //具体的类
        for (int i = 0; i < dataList.size(); i++) {
            ClassData classData = dataList.get(i);
            String field = classData.field;
            if (field.equals("serialVersionUID")) {
                continue;
            }
            if (field.equals("id")){
                builder.append("\t id  int4 DEFAULT nextval('"+ tabName +"_id_seq'::regclass)");
            }else {
                builder.append("\t \""+ field +"\"  "+ classData.type);
            }
            if (i < dataList.size() - 1) {
                builder.append(",\n");
            }else {
                builder.append("\n");
            }
        }

        builder.append(");\n\n");
        //设置主键
        builder.append("ALTER TABLE \"public\".\""+ tabName +"\" ADD CONSTRAINT \""+ tabName +"_pkey\" PRIMARY KEY (id);\n\n");
        //设置注释信息
        for (ClassData classData : dataList) {
            String desc = classData.desc;
            if (desc == null) {
                continue;
            }
            builder.append("COMMENT ON COLUMN \"public\".\""+ tabName +"\".\""+ classData.field +"\" IS '"+ desc +"';\n");
        }
        System.out.println(builder.toString());

    }

    /**
     * 使用反射解析实体类
     * @param clz
     * @return
     */
    public static List<ClassData> parseEntityClazz(Class clz){
        List<ClassData> dataList = new ArrayList<>();
        Field[] declaredFields = clz.getDeclaredFields();
        for (Field field : declaredFields) {
            ClassData classData = new ClassData();
            field.setAccessible(true);
            //转换名称
            String fieldName = field.getName();
            String newName = changeName(fieldName);
            classData.field = newName;
            //转换数据类型
            String type = field.getType().getSimpleName().toLowerCase();
            String newType = changeType(type);
            classData.type = newType;

            ApiModelProperty annotation = field.getAnnotation(ApiModelProperty.class);
            if (annotation != null) {
                String value = annotation.value();
                classData.desc = value;
            }
            dataList.add(classData);
        }
        return dataList;
    }

    /**
     * 转换数据类型
     * @param type
     * @return
     */
    private static String changeType(String type) {
        String sqlType = "";
        switch (type) {
            case "integer":
                sqlType = "int4";
                break;
            case "boolean":
                sqlType = "bool";
                break;
            case "char":
                sqlType = "char(4)";
                break;
            case "double":
                sqlType = "float8";
                break;
            case "date":
                sqlType = "timestamp";
                break;
            case "string":
            default:
                sqlType = "varchar(32)";
                break;
        }
        return sqlType;
    }

    /**
     * 名称转换为数据库规范
     * @param fieldName
     * @return
     */
    private static String changeName(String fieldName) {
        String sqlName = "";
        for (int i = 0;i < fieldName.length();i++) {
            char c = fieldName.charAt(i);
            if (i == 0) {
                sqlName += (c + "").toLowerCase();
            }else {
                char lastC = fieldName.charAt(i - 1);
                if ((lastC >= 'a' && lastC <= 'z') && (c >= 'A' && c <= 'Z')) {
                    sqlName += "_" + (c + "").toLowerCase();
                }else {
                    boolean f = false;
                    if (i < fieldName.length() - 1) {
                        char nextC = fieldName.charAt(i + 1);

                        if ((c >= 'A' && c <= 'Z') && (nextC >= 'a' && nextC <= 'z')) {
                            sqlName += "_" + (c + "").toLowerCase();
                            f = true;
                        }
                    }
                    if (!f) {
                        sqlName += (c + "").toLowerCase();
                    }
                }
            }
        }
        return sqlName;
    }

    public static class ClassData{
        public String field;
        public String desc;
        public String type;

    }

}
